#include "depui/depui.h"

#define MXMODULE_LIST

static void mx__themesel_geometry(MX_THEMESEL * sel)
{
	MXDEBUG_INVARIANT(MXOBJ(sel));

	mx_defaultrect(&sel->_ok, 0);
	mx_layout(&sel->_ok, (MX_LAYOUT_X2 | MX_LAYOUT_Y2), sel, 0, 0);
	mx_geometry(&sel->_ok);

	mx_defaultrect(&sel->_apply, 0);
	mx_layout(&sel->_apply, (MX_LAYOUT_LEFT | MX_LAYOUT_Y1), &sel->_ok, 2, 0);
	mx_geometry(&sel->_apply);

	mx_position(&sel->_themes, 0, 0, mx_w(sel), mx_y(&sel->_ok) - 1);
	mx_geometry(&sel->_themes);
}

/** This function refreshes a theme selector dialog with the currently
available themes.  This function should be called after creating the theme
selector and before it gets displayed or gets an MX_GEOMETRY event. */
void mx_themesel_refresh(MX_THEMESEL * sel)
{
	const MX_PLATFORM_RESOLUTION *r = 0;
	const MX_PLATFORM_DEPTH *c = 0;
	const MX_PLATFORM_DRIVER *d = 0;
	const MX_PLATFORM_THEME *t = 0;

	MXDEBUG_INVARIANT(MXOBJ(sel));

	mx_list_empty(&sel->_themes);

	/* Fill each of the lists with the gfx mode info */
	mx_platform_modes(&d, &r, &c, &t);
	if (t) {
		int num = 0;
		const MX_PLATFORM_THEME *ptr = t;

		while (ptr->text) {
			MX_LISTELEM *elem = mx_listelem((MX_LISTELEM *) 0, 0, &sel->_themes, num);

			mx_text_set(elem, ptr->text, -1, 0);
			mx_defaultrect(elem, 0);
			++ptr;
			++num;
		}
	}
	mx_geometry(&sel->_themes);
}

void mx_themesel_handler(MX_WIN * win)
{
	MX_THEMESEL *sel = (MX_THEMESEL *) win;

	MXDEBUG_INVARIANT(MXOBJ(win));
	MXDEBUG_INVARIANT(MXOBJ(mx.obj));

	if (mx_eventmatch(MX_GEOMETRY, sel)) {
		mx__themesel_geometry(sel);

	} else if (mx_eventmatch(MX_DEFAULTRECT, sel)) {
		MX_RECT *rrect = mx_defaultrect_data();

		rrect->x2 = rrect->x1 + 200;
		rrect->y2 = rrect->y1 + 120;
		return;

	} else if (mx_eventmatch(MX_LIST_CHANGED, &sel->_themes)) {
		int lindex = mx_list_selected_id(&sel->_themes);

				/**fix Error handling could be better here */
		if (lindex >= 0) {
			const MX_PLATFORM_RESOLUTION *r = 0;
			const MX_PLATFORM_DEPTH *c = 0;
			const MX_PLATFORM_DRIVER *d = 0;
			const MX_PLATFORM_THEME *t = 0;

			mx_platform_modes(&d, &r, &c, &t);
			if (t)
				sel->_chosen = t[lindex].theme;

			mx_disable(&sel->_ok, false);
			mx_disable(&sel->_apply, false);
		} else {
			sel->_chosen = 0;
			mx_disable(&sel->_ok, true);
			mx_disable(&sel->_apply, true);
		}

		mx_dirty(&sel->_ok, true);
		mx_dirty(&sel->_apply, true);
		return;

	} else if (mx_eventmatch(MX_SELECT, &sel->_ok)) {
		if (sel->_chosen) {
			const unsigned int ret = mx_inform(MX_THEMESEL_OK, sel, sizeof(sel));
			if ((!ret) && (sel->_chosen))
				mx_theme_set(sel->_chosen);

			mx_delete(sel);
			return;
		}

	} else if (mx_eventmatch(MX_SELECT, &sel->_apply)) {
		if (sel->_chosen) {
			const unsigned int ret = mx_inform(MX_THEMESEL_OK, sel, sizeof(sel));
			if ((!ret) && (sel->_chosen))
				mx_theme_set(sel->_chosen);

			return;
		}

	} else if (mx_eventmatch(MX_KEY_UNUSED, win)) {
		const MX_KEY_INFO *info = mx_key_info();

		if ((info) && (info->ascii == 0x1b)) {
			mx_win_dirty(sel);
			mx_delete(sel);
		}
	}

	mx_win_handler(win);
}

MX_THEMESEL *mx_themeselwin(MX_THEMESEL * sel, size_t size, MX_HANDLER handler, int theid)
{
	MXMINSIZE(size, MX_THEMESEL);

	if (!handler)
		handler = mx_themesel_handler;

	sel = (MX_THEMESEL *) mx_win(sel, size, handler, theid);
	if (sel) {
		MXDEBUG_ALLOCTAG(sel);
		MXDEBUG_ATOMNAME(sel, "themesel");
		mx_text_set(sel, "Choose theme", -1, 0);

		mx_button(&sel->_ok, 0, sel, 0);
		mx_text_set(&sel->_ok, "ok", -1, 0);
		mx_disable(&sel->_ok, true);
		MXDEBUG_ATOMNAME(&sel->_ok, "themesel_ok");

		mx_button(&sel->_apply, 0, sel, 0);
		mx_text_set(&sel->_apply, "apply", -1, 0);
		mx_disable(&sel->_apply, true);
		MXDEBUG_ATOMNAME(&sel->_apply, "themesel_apply");

		mx_list(&sel->_themes, 0, sel, 0);
/**fix          mx_text_set(&sel->_themes, "themes", -1, 0); */
		MXDEBUG_ATOMNAME(&sel->_themes, "themesel_themes");
	}

	MXDEBUG_INVARIANT(MXOBJ(sel));
	return sel;
}

/** !theme selection information
When a theme has been chosen from a theme selector dialog the a 
MX_THEMESEL_OK event is sent to the parent window.  This function can be called
when handling that event to determine the theme selected. */
const MX_THEME *mx_themesel_info(const int idnum)
{
	MX_THEMESEL *sel;

/** This function should only be called when handling an MX_THEMESEL_event. */
	assert(mx.event == MX_THEMESEL_OK);
	if (mx.event != MX_THEMESEL_OK)
		return 0;

	sel = (MX_THEMESEL *) mx.data;
	MXDEBUG_INVARIANT(MXOBJ(sel));

/** The sepcified id number has to match the one with the selected theme. */
	if ((sel) && (MXID(sel) == idnum))
		return sel->_chosen;

	return 0;
}
